﻿using System;
using System.Windows;
using System.Linq;
using Core.Infrastructure.AnimationService;
using Core.Infrastructure.Menu;
using Core.Infrastructure.ScreenManager;
using Core.Infrastructure.Settings;
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Unity;
using ThemeLoader;
using Core.ProxyService;
using RssProxyService;
using System.Collections;
using Core.Model;
using System.Collections.Generic;
using System.Net;
using Core.Infrastructure.ErrorReportService;
using Api.ContentProvider;
using System.Windows.Controls;
using Microsoft.Practices.Composite.Presentation.Regions;
using Microsoft.Practices.Composite.Regions;
using Core.Infrastructure.Constants;
using Core.ScreenStore.Screen;
using Core.ScreenStore.ViewModel;

namespace Core
{
    public class Config : IConfig
    {
        /// <summary>
        /// creates shell using IoC container and sets app root visual
        /// </summary>
        /// <returns>
        /// DependencyObject - ShellView
        /// </returns>
        public DependencyObject CreateAndSetRootVisual(IUnityContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("Unity container must be set");
            }
            this.ShellView = container.Resolve<ShellView>();
            this.ShellView.Style = Application.Current.Resources["ShellViewStyle"] as Style;
            var rootGrid = Application.Current.RootVisual as Grid;
            rootGrid.Children.Clear();
            rootGrid.Children.Add(this.ShellView);
            return this.ShellView;
        }

        /// <summary>
        /// Retasurns modules catalog loaded from xaml
        /// </summary>
        /// <param name="uri">String uri</param>
        /// <returns>IModuleCatalog</returns>
        public IModuleCatalog CreateModuleCatalog(String uri)
        {
            if (String.IsNullOrEmpty(uri))
            {
                throw new ArgumentNullException("Path to module catalog must be set");
            }

            Uri _uri = new Uri(uri, UriKind.Relative);

            return CreateModuleCatalog(_uri);
        }

        /// <summary>
        /// Retasurns modules catalog loaded from xaml
        /// </summary>
        /// <returns></returns>
        public IModuleCatalog CreateModuleCatalog(Uri uri)
        {
            return ModuleCatalog.CreateFromXaml(uri);
        }

        /// <summary>
        /// Initializes application resources, registers services in IoC container
        /// </summary>
        public void Initialize(IUnityContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("Unity container must be specified");
            }
            // master page marriage
            container.RegisterType<IShellViewModel, ShellViewModel>();
            container.RegisterType<IMenu, Menu>();
        }

        public ShellView ShellView { get; set; }

        //public IUnityContainer UnityContainer { get; set; }

        public void RegisterThemeLoaders(IUnityContainer container)
        {
            IEnumerable<ThemeModel> themes = new List<ThemeModel>()
            {
                new ThemeModel()
                {
                    Name = "Orginal",
                    ZippedThemeFilePath = "CompressedThemes/ApplicationStyles.zip",
                    ResourcePath = "ApplicationStyles.xaml",
                },
                new ThemeModel()
                {
                    Name = "Metro",
                    ZippedThemeFilePath = "CompressedThemes/MetroStyles.zip",
                    ResourcePath = "MetroStyles.xaml",
                },
            };

            Action recreateView = () => 
                {
                    var rootGrid = Application.Current.RootVisual as Grid;
                    var oldShell = rootGrid.Children[0] as ShellView;

                    oldShell.MainRegion.Content = null;

                    var newShell = CreateAndSetRootVisual(container) as Control;
                    newShell.DataContext = container.Resolve<IShellViewModel>();
                };

            IResourceProvider resourceProvider= new DelegateResourceProvider(() => App.Current.Resources);
            container.RegisterInstance(typeof(IResourceProvider), resourceProvider);

            ThemeManager themeManager = new ThemeManager(resourceProvider, recreateView);
            container.RegisterInstance(typeof(IThemeManager),themeManager);
            container.RegisterInstance(typeof(IEnumerable<ThemeModel>), themes);
            container.RegisterType<IThemeLoader, ThemeLoader.ThemeLoader>(new ContainerControlledLifetimeManager());
        }

        public void RegisterScreenManeger(IUnityContainer container)
        {
            if (container == null)
                throw new ArgumentNullException("Unity container must be specified");

            container.RegisterType<IScreenFactoryRegistry, ScreenFactoryRegistry>(
                new ContainerControlledLifetimeManager());

            container.RegisterType<ScreenManager, ScreenManager>(
                new ContainerControlledLifetimeManager());

            var screenManager = container.Resolve<ScreenManager>();
        }

        public IUnityContainer CreateUnityContainer()
        {
            return new UnityContainer();
        }

        public void RegisterServices(IUnityContainer container)
        {
            //new ContainerControlledLifetimeManager() -> means singleton
            //Container.RegisterType<IBusyService, BusyService>(new ContainerControlledLifetimeManager());//busy animation singleton

            ContentControlViewInjector injector = new ContentControlViewInjector(() =>
                {
                    var rootGrid = Application.Current.RootVisual as Grid;
                    var shellView = rootGrid.Children[0] as ShellView;
                    return shellView.MainRegion;
                });

            container.RegisterInstance<IViewInjector>(injector);

            container.RegisterType<IAnimationService, AnimationService>(new ContainerControlledLifetimeManager());// animation service singleton
            container.RegisterType<ISettings, Settings>(new ContainerControlledLifetimeManager());//app config


            Func<WebClient> webClientFactory = () => new WebClient();

            var prophetService = new RssProxyService.RssProxyService(webClientFactory, "http://the-prophet.tumblr.com/rss", new RssMapper());
            var flickerService = new RssProxyService.RssProxyService(webClientFactory, "http://api.flickr.com/services/feeds/photos_public.gne", new FlickerRssMapper());
            var designService = new DesignProxyService();

            var compositeProxyService = new CompositeProxyService.CompositeProxyService(prophetService, flickerService, designService);

            container.RegisterInstance<ICoreProxyService>(compositeProxyService);

            var errorReporterService = new DelegateErrorReportService(message => MessageBox.Show(message));
            container.RegisterInstance<IErrorReportService>(errorReporterService);
            container.RegisterType<IContentProvider, DefaultContentProvider.DefaultContentProvider>();
            container.RegisterType<IArticlesModel, ArticlesModel>(new ContainerControlledLifetimeManager()); 
        }


        public void SetupShellViewModel(IUnityContainer container)
        {
            container.RegisterType<ShellView>(new TransientLifetimeManager());
            var shellViewModel = container.Resolve<IShellViewModel>();
            ShellView.DataContext = shellViewModel;
            ScreenManager manager = container.Resolve<ScreenManager>();
            manager.CreateScreenIfNeccessary(ScreenType.ArticleDetailsScreen);
        }
    }
}
